/*
    从二进制文件中读取数据，反序列化到通讯录对象中，实现打印所有联系人的方法
*/
#include <iostream>
#include <fstream>
#include "address_book.pb.h"

// 打印所有联系人
void PrintContacts(const addressbook::AddressBook& addressBook)
{
    int n = addressBook.contacts_size();
    for(int i = 0; i < n; i++)
    {
        const addressbook::Contacts& ct = addressBook.contacts(i);  
        std::cout << "-----------------联系人" << i+1 << "-----------------" << std::endl;
        std::cout << "姓名：" << ct.name() << std::endl;
        std::cout << "年龄：" << ct.age() << std::endl;
        int m = ct.phones_size();
        for(int j = 0; j < m; j++)
        {
            const addressbook::Contacts_Phone& phone = ct.phones(j);
            std::cout << "电话" << j+1 << ": " << phone.number() 
                << "(" << phone.Type_Name(phone.type()) << ")" << std::endl; // Type_Name可以将枚举值转换为值名
            // 如果枚举值没有被设置，protobuf会使用默认值0填充
        }

        // 注意：下面的Is()判断是否是指定message类型，以及UnpackTo()解析函数是由Any类型提供的，不是Contacts类型提供的
        if(ct.has_address() && ct.address().Is<addressbook::Address>()) // 判断地址中是否有数据 && 数据是否是Address类型
        {
            addressbook::Address addr;
            ct.address().UnpackTo(&addr); // 将数据从Any类型解析到对应的类型
            std::cout << "家庭地址：" << addr.home_address() << std::endl;
            std::cout << "单位地址：" << addr.unit_address() << std::endl;
        }

        // 利用switch判断联系方式是哪种，不用ct.has_qq()或ct.has_wechat()
        addressbook::Contacts::ContactInfoCase contactInfoType = ct.contact_info_case(); // 此函数会返回一个枚举类型
        switch(contactInfoType)
        {
        case addressbook::Contacts::ContactInfoCase::kQq:
            std::cout << "QQ: " << ct.qq() << std::endl;
            break;
        case addressbook::Contacts::ContactInfoCase::kWechat:
            std::cout << "微信：" << ct.wechat() << std::endl;
            break;
        case addressbook::Contacts::ContactInfoCase::CONTACT_INFO_NOT_SET:
            break;
        }

        if(ct.commits_size())
        {
            std::cout << "备注信息：" << std::endl;
        }
        for(auto it = ct.commits().begin(); it != ct.commits().end(); it++)
        {
            std::cout << "  " << it->first << ": " << it->second << std::endl;
        }
    }
}
int main()
{
    // 1. 打开文件，如果存在从文件中加载数据
    std::fstream input("address_book.bin", std::ios::in | std::ios::binary);
    addressbook::AddressBook addressBook;
    if(input) // 文件存在
    {
        bool ret = addressBook.ParseFromIstream(&input); // 从文件流中反序列化
        input.close();
        if(ret == false)
        {
            std::cout << "从文件中反序列化通讯录失败" << std::endl;
            return -1;
        }
    }
    else
    {
        std::cout << "文件不存在" << std::endl;
        return -1;
    }

    // 2. 打印所有联系人
    PrintContacts(addressBook);
    return 0;
}